/**
 * 图灵机核心逻辑模块
 * @module turingMachine
 */

import { DIRECTION, DEFAULT_TAPE_LENGTH, DEFAULT_HEAD_POSITION, DEFAULT_BYTE_SIZE, DEFAULT_STATE, DEFAULT_SYMBOL, ERROR_MESSAGES } from './constants.js';
import { compressAndStore, loadAndDecompress, addHistory } from './storage.js';

/**
 * 图灵机类
 */
class TuringMachine {
    constructor() {
        const savedState = loadAndDecompress();
        
        if (savedState) {
            this.tape = savedState.tape;
            this.headPosition = savedState.headPosition;
            this.byteSize = savedState.byteSize;
            this.currentState = savedState.currentState;
            this.cache = savedState.cache;
        } else {
            this.tape = Array(DEFAULT_TAPE_LENGTH).fill(DEFAULT_SYMBOL);
            this.headPosition = DEFAULT_HEAD_POSITION;
            this.byteSize = DEFAULT_BYTE_SIZE;
            this.currentState = DEFAULT_STATE;
            this.cache = [];
        }

        this.stepCount = 0;
        this.isRunning = false;
        this.halted = false;
    }

    /**
     * 移动读写头
     * @param {'L'|'R'|'S'} direction 移动方向
     * @param {number} steps 移动步数
     * @throws {Error} 如果方向无效或超出纸带范围
     */
    move(direction, steps = 1) {
        if (!Object.values(DIRECTION).includes(direction)) {
            throw new Error(ERROR_MESSAGES.INVALID_DIRECTION);
        }

        if (direction === DIRECTION.LEFT) {
            this.headPosition = Math.max(0, this.headPosition - steps);
        } else if (direction === DIRECTION.RIGHT) {
            this.headPosition = Math.min(this.tape.length - 1, this.headPosition + steps);
        }

        this.saveState();
    }

    /**
     * 读取当前位置的值
     * @returns {string} 当前单元格的值
     */
    read() {
        return this.tape[this.headPosition];
    }

    /**
     * 写入值到当前位置
     * @param {string} value 要写入的值
     * @throws {Error} 如果值不是有效的2位十六进制
     */
    write(value) {
        if (!/^[0-9A-Fa-f]{2}$/.test(value)) {
            throw new Error(ERROR_MESSAGES.INVALID_HEX_VALUE);
        }

        this.tape[this.headPosition] = value.toUpperCase();
        this.saveState();
    }

    /**
     * 设置字节大小
     * @param {number} size 字节大小(1-8)
     * @throws {Error} 如果大小无效
     */
    setByteSize(size) {
        if (size < 1 || size > 8 || !Number.isInteger(size)) {
            throw new Error(ERROR_MESSAGES.INVALID_BYTE_SIZE);
        }
        this.byteSize = size;
        this.saveState();
    }

    /**
     * 从纸带加载数据到缓存
     * @param {number} position 起始位置
     * @param {number} length 要读取的字节数
     * @throws {Error} 如果位置无效
     */
    loadToCache(position, length) {
        if (position < 0 || position >= this.tape.length) {
            throw new Error(ERROR_MESSAGES.INVALID_POSITION);
        }

        const endPos = Math.min(position + length, this.tape.length);
        this.cache = this.tape.slice(position, endPos);
        this.saveState();
    }

    /**
     * 将缓存数据写入纸带
     * @param {number} position 起始位置
     * @throws {Error} 如果位置无效
     */
    storeFromCache(position) {
        if (position < 0 || position >= this.tape.length) {
            throw new Error(ERROR_MESSAGES.INVALID_POSITION);
        }

        for (let i = 0; i < this.cache.length && position + i < this.tape.length; i++) {
            this.tape[position + i] = this.cache[i];
        }

        this.saveState();
    }

    /**
     * 清空缓存
     */
    clearCache() {
        this.cache = [];
        this.saveState();
    }

    /**
     * 执行单条指令
     * @param {Array} instruction 五元组指令 [当前状态, 读取值, 写入值, 移动方向, 下一状态]
     * @returns {boolean} 是否成功执行
     */
    executeInstruction(instruction) {
        if (!this.validateInstruction(instruction)) {
            return false;
        }

        const [currentState, readValue, cachePosition, direction, nextState] = instruction;

    // 调试输出
    console.log('Executing instruction:', instruction);
    console.log('Current state:', this.currentState, 'Tape value:', this.read());
        // 检查当前状态是否匹配
        if (this.currentState !== currentState) {
            return false;
        }

         // 新读取逻辑
        if (readValue !== '*') {
          // 将readValue解释为要读取的长度（十六进制转十进制）
          const length = parseInt(readValue, 16) || 1;
          this.loadToCache(this.headPosition, length);
          console.log(`读取 ${length} 字节到缓存:`, this.cache);
        }

          // 新写入逻辑（从缓存读取数据写入纸带）
          if (Array.isArray(cachePosition) && cachePosition[0]=== 'c') {
            // 
            const cachePos = parseInt(cachePosition[1], 16);
            
            if (cachePos >= 0 && cachePos < this.cache.length) {
                const valueFromCache = this.cache[cachePos];
                if (!valueFromCache) {
                    console.warn(`缓存位置 ${cachePos} 无数据，写入默认值 00`);
                    this.write('00');
                } else {
                    this.write(valueFromCache);
                    console.log(`从缓存[${cachePos}]写入值 ${valueFromCache} 到纸带位置 ${this.headPosition}`);
                }
            } else {
                console.warn(`缓存位置 ${cachePos} 越界 (缓存大小: ${this.cache.length})`);
                this.write('00'); // 越界时写入默认值
            }
          } else  if (cachePosition !== '*') {
            // 
            this.write(cachePosition);
        }



        // 执行移动
        this.move(direction);

        // 更新状态
        this.currentState = nextState;
        this.stepCount++;
        
        // 记录历史
        addHistory(instruction, this.stepCount);

        this.saveState();
        return true;
    }

    /**
     * 验证指令格式
     * @param {Array} instruction 待验证的指令
     * @returns {boolean} 是否有效
     */
    validateInstruction(instruction) {
      if (!Array.isArray(instruction) || instruction.length !== 5) {
          return false;
      }
  
      const [currentState, readValue, writeValue, direction, nextState] = instruction;
  
      // 检查状态格式（保持不变）
      if (typeof currentState !== 'string' || typeof nextState !== 'string') {
          return false;
      }
  
      // 增强的读写值格式检查
      const isValidHex = v => /^[0-9A-Fa-f]{2}$/.test(v);
      const isValidCacheRef = v => 
          Array.isArray(v) &&
          v.length === 2 &&
          isValidHex(v[1]);
  
      if (
          (readValue !== '*' && !isValidHex(readValue)) ||
          (writeValue !== '*' && !isValidHex(writeValue) && !isValidCacheRef(writeValue))
      ) {
          return false;
      }
  
      // 检查移动方向（保持不变）
      if (!Object.values(DIRECTION).includes(direction)) {
          return false;
      }
  
      return true;
  }

    /**
     * 停机
     */
    halt() {
        this.halted = true;
        this.isRunning = false;
        this.currentState = 'halt';
        this.saveState();
    }

    /**
     * 重置图灵机
     */
    reset() {
        this.tape = Array(DEFAULT_TAPE_LENGTH).fill(DEFAULT_SYMBOL);
        this.headPosition = DEFAULT_HEAD_POSITION;
        this.byteSize = DEFAULT_BYTE_SIZE;
        this.currentState = DEFAULT_STATE;
        this.cache = [];
        this.stepCount = 0;
        this.isRunning = false;
        this.halted = false;
        this.saveState();
    }

    /**
     * 保存当前状态到存储
     */
    saveState() {
        compressAndStore({
            tape: this.tape,
            headPosition: this.headPosition,
            byteSize: this.byteSize,
            currentState: this.currentState,
            cache: this.cache
        });
    }

    /**
     * 扩展纸带
     * @param {number} amount 扩展数量
     * @param {'left'|'right'} side 扩展方向
     */
    expandTape(amount, side = 'right') {
        const newCells = Array(amount).fill(DEFAULT_SYMBOL);
        
        if (side === 'left') {
            this.tape = [...newCells, ...this.tape];
            this.headPosition += amount;
        } else {
            this.tape = [...this.tape, ...newCells];
        }
        
        this.saveState();
    }
}

export default TuringMachine;